
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include "printarsudoku.c"
#include "printarmissing.c"
#include "ddq.c"
#include "mMulti.c"
#include "vGeral.c"
#include "vComplete.c"
#include "knightofone.c"
#include "knightoftwo.c"
#include "knightofzero.c"
#include "knightsofround.c" 
int main ()
{
	// Copyrighted code. @2013 - /Dev Company
  	srand((unsigned int)time(0));
  	char confirm;
  	time_t t0;
	short int sudoku[9][9],missing[27][10],linha,coluna, isValid=0, tryCount=1,tryCounter0=0,tryCounter1=0,quadro,x,y;
	while (isValid==0)
	{
		system("clear");
		//printf("Insira o Sudoku, casa por casa e sequencialmente. O programa cuidará do resto.\nObs: Vazios são representados por 0.\n");  // portuguese shit
		printf("Insert sudoku, one tile at a time.\nPs.: Empty tiles = 0\n"); // merda americana
		for (linha=0;linha<9;linha++)
		{
			for (coluna=0;coluna<9;coluna++)
			{
				sudoku[linha][coluna]=63;
			}
		}
		for (linha=0;linha<9;linha++)
		{
			for (coluna=0;coluna<9;coluna++)
			{
				while (sudoku[linha][coluna]>9 || sudoku[linha][coluna]<0)
				{
					scanf("%hu",&sudoku[linha][coluna]);
					if (sudoku[linha][coluna]<0)
					{
						y = -1*sudoku[linha][coluna]+1;
						for (x=0;x<y;x++)
						{
							sudoku[linha][coluna-x]=63;
						}
						for (x=0;x<y;x++)
						{
							coluna=(&sudoku[0][0]!=&sudoku[linha][coluna])?coluna-1:coluna;
						}						
						system("clear");
						printf("<><><><><><><><><><><><><><><><><><><><><><>\n\nPreview:\n");
						printarSudoku(sudoku);
						//printf("Digite -x para apagar x casas anteriores.\nAs casas vazias devem ser representadas por 0.\n"); // Portuguese shit
						printf("Insert -[number] to erase a number of previous tiles.\nPs.: Empty tiles = 0\n");
					}
				}
				system("clear");
				printf("<><><><><><><><><><><><><><><><><><><><><><>\n\nPreview:\n");
				printarSudoku(sudoku);
				printf("Insert -[number] to erase a number of previous tiles.\nPs.: Empty tiles = 0\n");
			}
		}
		//// SET DO SUDOKU COM VERIFICADOR DE ERRO ACIMA
		for (linha=0;linha<27;linha++)
		{
			for (coluna=0;coluna<10;coluna++)
			{
				missing[linha][coluna]=0;
			}
		}
		/// PRE SET MISSING ACIMA

		for (linha=0;linha<9;linha++)
		{
			for (coluna=0;coluna<9;coluna++)
			{
				quadro=ddq(linha,coluna);
				switch (sudoku[linha][coluna])
				{
					case 0:
						missing[linha][9]++;
						missing[coluna+9][9]++;
						missing[quadro+18][9]++;
						break;
					case 1:
						missing[linha][0]++;
						missing[coluna+9][0]++;
						missing[quadro+18][0]++;
						break;
					case 2:
						missing[linha][1]++;
						missing[coluna+9][1]++;
						missing[quadro+18][1]++;
						break;
					case 3:
						missing[linha][2]++;
						missing[coluna+9][2]++;
						missing[quadro+18][2]++;
						break;
					case 4:
						missing[linha][3]++;
						missing[coluna+9][3]++;
						missing[quadro+18][3]++;
						break;
					case 5:
						missing[linha][4]++;
						missing[coluna+9][4]++;
						missing[quadro+18][4]++;
						break;
					case 6:
						missing[linha][5]++;
						missing[coluna+9][5]++;
						missing[quadro+18][5]++;
						break;
					case 7:
						missing[linha][6]++;
						missing[coluna+9][6]++;
						missing[quadro+18][6]++;
						break;
					case 8:
						missing[linha][7]++;
						missing[coluna+9][7]++;
						missing[quadro+18][7]++;
						break;
					case 9:
						missing[linha][8]++;
						missing[coluna+9][8]++;
						missing[quadro+18][8]++;
						break;
				}
			
			}
		}
		/// SET MISSING ACIMA
		isValid = vGeral(sudoku,missing);
		system("clear");
		printf("<><><><><><><><><><><><><><><><><><><><><><>\n");
		printarSudoku(sudoku);
		//printf("<><><><><><><><><><><><><><><><><><><><><><>\n\nO Sudoku digitado está correto? (S/N)\n"); //portuguese shit
		printf("<><><><><><><><><><><><><><><><><><><><><><>\n\nIs the inserted Sudoku correct? (Y/N)\n");
		//printf("%s", (vGeral(sudoku,missing)==0)?"Alerta: Sudoku inválido.\n":""); portuguese shit
		printf("%s", (vGeral(sudoku,missing)==0)?"Warning: Invalid Sudoku.\n":"");
		getchar();
		scanf("%c",&confirm);
		isValid = (confirm=='N' || confirm=='n') ? 0:isValid;
	}

	t0 = time (NULL);

	while (tryCount<7000)
	{
		system("clear");
		//printf("%s\n",(tryCount<1000) ? "Processando... Aguarde :)":"Processando... Aguarde :/"); // portuguese shit
		printf("%s\n",(tryCount<1000) ? "Wait. Space monkeys working.":"Just a moment. The monkeys are in trouble with some aliens."); // legit brazilian joke
		tryCounter0++;
		tryCount = (KnightsOfRound(sudoku,missing,0)==1) ? 20001:tryCount+1;
	}
	tryCount = (tryCount==7000) ? 0:tryCount;
	while (tryCount<20000)
	{
		system("clear");
		printf("%s\n",(tryCount<1000) ? "Wait. Space monkeys working.":"Just a moment. The monkeys are in trouble with some aliens."); // legit brazilian joke2x
		tryCounter1++;
		tryCount = (KnightsOfRound(sudoku,missing,1)==1) ? 20001:tryCount+1;
	}
	if (tryCount==20000)
	{
		system("clear");
		//printf("Solução não encontrada. D: \n Seria o Sudoku inserido um Sudoku sem resposta?\n\n"); //portuguese shit
		printf("We couldn't find the solution. \n Would it be a problem with the inserted Sudoku?\n");
	}
	//printf("     -Número total de tentativas: %d.\n     -Tempo total de execução: %.2f minutos.\n     -Velocidade média: %.0f execuções por segundo.\n\n A unLimitedDev agradece o uso.\n\n",tryCounter0+tryCounter1,(float)(time (NULL)-t0)/60,(float)(tryCounter0+tryCounter1)/(time (NULL)-t0)); //portuguese random shit
	printf("     -Total attempts: %d.\n     -Total runtime: %.2f minutes.\n     -Average speed: %.0f cycles per second. (usually inf, cause your computer is so badass)\n\n Thank you for using the UltimeSudokuSolver.\n /Dev Company.\n\n",tryCounter0+tryCounter1,(float)(time (NULL)-t0)/60,(float)(tryCounter0+tryCounter1)/(time (NULL)-t0));
	// KNIGHTS OF ROUND ACIMA

	return 0;
	// Copyrighted code. @2013 - /Dev Company
}